<?php

	namespace org\tekuna\framework\filter\data;


	use \OutOfRangeException;
	use \InvalidArgumentException;

	use org\tekuna\framework\filter\Filter;
	use org\tekuna\framework\filter\FileFilter;


	/**
	 * The FilterChain filter allows to apply multiple filters in
	 * successively on one request value. The constructor awaites
	 * multiple parameters that are all Filter implementations.
	 * The filter() method applies these filters one after another.
	 */
	class FilterChain implements Filter {

		protected $arrFilters = array();


		/**
		 * Constructor to build a new filter chain out of a bunch
		 * of given TekunaFilters. Parameters are accepted as much
		 * as you provide, but at least one.
		 *
		 * @param Filter $objFilter(1)
		 * @param Filter $objFilter(2)
		 *                     ...
		 * @param Filter $objFilter(n)
		 */
		public function __construct() {

			$iNumArgs = func_num_args();

			// check argument count
			if ($iNumArgs < 1) {

				throw new OutOfRangeException('The construction of a filter chain requires at least one Filter object argument.');
			}

			// check argument types
			for ($i = 0; $i < $iNumArgs; $i++) {

				// get the nth argument
				$mArgument = func_get_arg($i);

				// check if the argument is an object of type TekunaFilter
				if (is_object($mArgument) && $mArgument instanceof Filter) {

					// add filter object to the filter list
					$this -> arrFilters[] = $mArgument;
				}
				else {

					throw new InvalidArgumentException("Argument #$i is not an object of type org\\tekuna\\framework\\filter\\Filter.");
				}
			}
		}


		/**
		 * Apply all the registered filters to a given input
		 *
		 * @param mixed $mInput the unfiltered input
		 * @return mixed the multiple filtered output
		 */
		public function filter($mInput) {

			// iterate all filters
			foreach ($this -> arrFilters as $objFilter) {

				// apply each filter method to the given input
				$mInput = $objFilter -> filter($mInput);
			}

			// return the multiple-filtered input
			return $mInput;
		}
	}
